package org.ayou.http;

import java.util.concurrent.TimeUnit;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.HttpConnectionFactory;
import org.apache.http.conn.ManagedHttpClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;

public class HttpClientPool {
	static PoolingHttpClientConnectionManager manager = null;
	static CloseableHttpClient httpClient = null;

	public static synchronized CloseableHttpClient getHttpClient() {
		if (httpClient != null) {
			// 注册访问协议相关的Socket工厂
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE)
					.register("https", SSLConnectionSocketFactory.getSystemSocketFactory()).build();

			// HttpConnection工程：配置写请求/解析响应处理器
			HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
					DefaultHttpRequestWriterFactory.INSTANCE, DefaultHttpResponseParserFactory.INSTANCE);

			// DNS解析器
			DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;

			// 创建池化链接管理器
			manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, connFactory, dnsResolver);

			// 默认为socket配置
			SocketConfig defaultSocketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
			manager.setDefaultSocketConfig(defaultSocketConfig);

			manager.setMaxTotal(300);// 连接池最大300
			manager.setDefaultMaxPerRoute(200);// 每个路由最大连接数

			// 在从连接池获取链接时，链接不活跃多长时间后需要进行一次验证，默认为2s
			manager.setValidateAfterInactivity(5 * 1000);

			// 默认请求配置
			RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(2 * 1000)
					.setSocketTimeout(5 * 1000).setConnectionRequestTimeout(2000).build();

			// 创建HttpClient
			httpClient = HttpClients.custom().setConnectionManager(manager).setConnectionManagerShared(false)
					.evictIdleConnections(60, TimeUnit.SECONDS).evictExpiredConnections()
					.setDefaultRequestConfig(defaultRequestConfig)
					.setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)
					.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
					.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();

			// jvm停止活启动，关闭连接池释放掉连接（跟数据库连接池类似）
			Runtime.getRuntime().addShutdownHook(new Thread(() -> {
				try {
					httpClient.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}));

		}
		return httpClient;
	}
}
